home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1997 #1
/
Amiga Plus CD - 1997 - No. 01.iso
/
pd
/
programmierung
/
oberonv4
/
demos
/
obtris.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1996-02-15
|
24KB
|
774 lines
Syntax10.Scn.Fnt
Syntax10b.Scn.Fnt
Syntax14b.Scn.Fnt
FoldElems
ParcElems
Alloc
MODULE ObTris; (** V1.0 (C) 1 Nov 1995 by Ralf Degner, E-Mail: degner@pallas.amp.uni-hannover.de *)
(* If you use MacOberon or the Ceres replace Input.TimeUnit by 300 *)
IMPORT
Oberon, Viewers, Display, MenuViewers, TextFrames, Texts, Files, Input;
CONST
red=1; blue=3; green=2; yellow=4; col1=5; col2=6; col3=7;
Menu = "System.Close System.Copy System.Grow ObTris.Start ObTris.ShowNext ObTris.Score";
XAnzahl=10; YAnzahl=24; MinKasten=4;
UntenOffset=10; ObenOffset=4; SeitenOffset=10; NextXPos=-5; NextYPos=YAnzahl DIV 2;
LinesProLevel=10; SpeedUpProLevel=20; ScoreFakt=10; ScoreFileMark=06C6F6976H;
String = ARRAY 32 OF CHAR;
Game = POINTER TO GameDesc;
GameDesc = RECORD
Field: ARRAY XAnzahl+2 OF ARRAY YAnzahl+2 OF INTEGER;
Runs, ShowNext: BOOLEAN;
Delay, Score, Level, Lines: LONGINT;
x, y, p, fig, next: INTEGER;
END;
Frame = POINTER TO FrameDesc;
FrameDesc = RECORD(Display.FrameDesc)
XOffset, YOffset: INTEGER;
Kasten: INTEGER;
Aktiv: BOOLEAN;
G: Game;
END;
ObTrisMsg = RECORD(Display.FrameMsg)
END;
DrawMsg = RECORD(ObTrisMsg)
G: Game;
END;
W: Texts.Writer;
Name: String;
Seed, Delay: LONGINT;
Fig: ARRAY 8 OF ARRAY 4 OF ARRAY 4 OF ARRAY 4 OF INTEGER;
FigSize: ARRAY 8 OF INTEGER;
HiScore, HiLevel, HiLines: ARRAY 10 OF LONGINT;
HiName: ARRAY 10 OF String;
ScoreFile: Files.File;
ScoreRider: Files.Rider;
ch: ARRAY 7 OF CHAR;
(* Generate Random Numbers *)
PROCEDURE Random(Ein: INTEGER):INTEGER;
CONST a=16807; m=2147483647; q=m DIV a; r=m MOD a;
VAR g: LONGINT;
BEGIN
g:=a*(Seed MOD q)-r*(Seed DIV q);
IF g>0 THEN Seed:=g
ELSE Seed:=g+m END;
RETURN SHORT(Seed) MOD Ein
END Random;
(* Print current Keys *)
PROCEDURE PrintKeys();
VAR d: INTEGER;
BEGIN
Texts.WriteString(W, "Current Keys: ");
FOR d:=0 TO 5 DO
IF ch[d]=CHR(193) THEN Texts.WriteString(W, "UP")
ELSIF ch[d]=CHR(194) THEN Texts.WriteString(W, "DOWN")
ELSIF ch[d]=CHR(196) THEN Texts.WriteString(W, "LEFT")
ELSIF ch[d]=CHR(195) THEN Texts.WriteString(W, "RIGHT")
ELSIF ch[d]=CHR(13) THEN Texts.WriteString(W, "RETURN")
ELSIF ch[d]=CHR(27) THEN Texts.WriteString(W, "ESC")
ELSIF ch[d]=CHR(9) THEN Texts.WriteString(W, "TAB")
ELSIF ch[d]=" " THEN Texts.WriteString(W, "SPACE")
ELSE Texts.Write(W, ch[d]);
END;
Texts.Write(W, " ");
END;
Texts.WriteLn(W);
END PrintKeys;
(* Store HiScore *)
PROCEDURE SaveHi(Register: BOOLEAN);
VAR d: INTEGER;
BEGIN
Files.Set(ScoreRider, ScoreFile, 0);
Files.WriteLInt(ScoreRider, ScoreFileMark);
FOR d:=0 TO 5 DO
Files.Write(ScoreRider, ch[d])
END;
FOR d:=0 TO 9 DO
Files.WriteBytes(ScoreRider, HiName[d], 32);
Files.WriteLInt(ScoreRider, HiScore[d]);
Files.WriteLInt(ScoreRider, HiLevel[d]);
Files.WriteLInt(ScoreRider, HiLines[d]);
END;
IF Register THEN
Files.Register(ScoreFile)
ELSE
Files.Close(ScoreFile)
END
END SaveHi;
(* Load HiScore *)
PROCEDURE LoadHi();
d: INTEGER;
m: LONGINT;
PROCEDURE ClearHi();
VAR n: INTEGER;
BEGIN
ch[0]:="j"; ch[1]:="k"; ch[2]:="i"; ch[3]:="m"; ch[4]:="h"; ch[5]:="p";
FOR n:=0 TO 9 DO
HiScore[n]:=0; HiLevel[n]:=0; HiLines[n]:=0;
COPY("Amiga", HiName[n])
END
END ClearHi;
BEGIN
ScoreFile:=Files.Old("ObTris.Score");
IF ScoreFile=NIL THEN
ScoreFile:=Files.New("ObTris.Score");
ClearHi();
SaveHi(TRUE)
ELSE
Files.Set(ScoreRider, ScoreFile, 0);
Files.ReadLInt(ScoreRider, m);
IF m=ScoreFileMark THEN
FOR d:=0 TO 5 DO
Files.Read(ScoreRider, ch[d])
END;
FOR d:=0 TO 9 DO
Files.ReadBytes(ScoreRider, HiName[d], 32);
Files.ReadLInt(ScoreRider, HiScore[d]);
Files.ReadLInt(ScoreRider, HiLevel[d]);
Files.ReadLInt(ScoreRider, HiLines[d])
END
ELSE
ClearHi();
SaveHi(FALSE)
END
END LoadHi;
(* New Score for Hall of Fame ? If Yes, Register *)
PROCEDURE RegisterScore(s, le, li: LONGINT);
VAR d, n: LONGINT;
BEGIN
d:=9;
WHILE (d#-1) & (HiScore[d]<s) DO DEC(d); END;
IF d#9 THEN
INC(d);
IF d<9 THEN
FOR n:=8 TO d BY -1 DO
HiName[n+1]:=HiName[n]; HiScore[n+1]:=HiScore[n];
HiLevel[n+1]:=HiLevel[n]; HiLines[n+1]:=HiLines[n]
END
END;
HiName[d]:=Name; HiScore[d]:=s;
HiLevel[d]:=le; HiLines[d]:=li;
Texts.WriteString(W, "Entering Hall of Fame ..."); Texts.WriteLn(W);
SaveHi(FALSE)
END RegisterScore;
(* Draw one Kasten *)
PROCEDURE DrawKasten(f: Frame; x, y, Mode: INTEGER);
VAR XDum, YDum: INTEGER;
BEGIN
XDum:=f.XOffset+(f.Kasten*(x-1));
YDum:=f.YOffset+(f.Kasten*(y-1));
Display.ReplConst(Display.white, XDum, YDum, f.Kasten-1, f.Kasten-1, Display.paint);
Display.ReplConst(Mode, XDum+1, YDum+1, f.Kasten-3, f.Kasten-3, Display.paint)
END DrawKasten;
(* Clear one Kasten *)
PROCEDURE ClearKasten(f: Frame; x, y: INTEGER);
VAR XDum, YDum: INTEGER;
BEGIN
XDum:=f.XOffset+(f.Kasten*(x-1));
YDum:=f.YOffset+(f.Kasten*(y-1));
Display.ReplConst(Display.black, XDum, YDum, f.Kasten-1, f.Kasten-1, Display.paint)
END ClearKasten;
(* Draw Figure *)
PROCEDURE DrawFig(f: Frame; x, y, fi, pos: INTEGER);
VAR CountX, CountY, col: INTEGER;
BEGIN
FOR CountX:= 0 TO 3 DO
FOR CountY:= 0 TO 3 DO
col:=Fig[fi, pos,CountX,CountY];
IF col#0 THEN DrawKasten(f, CountX+x, CountY+y, col) END
END
END DrawFig;
(* Clear Figure *)
PROCEDURE ClearFig(f: Frame; x, y, fi, pos: INTEGER);
VAR CountX, CountY, col: INTEGER;
BEGIN
FOR CountX:= 0 TO 3 DO
FOR CountY:= 0 TO 3 DO
col:=Fig[fi, pos,CountX,CountY];
IF col#0 THEN ClearKasten(f, CountX+x, CountY+y) END
END
END ClearFig;
(* Register Figure at Field *)
PROCEDURE RegisterFig(G: Game; x, y, fi, pos: INTEGER);
VAR CX, CY, col: INTEGER;
BEGIN
FOR CX:= 0 TO 3 DO
FOR CY:= 0 TO 3 DO
col:=Fig[fi, pos,CX,CY];
IF col#0 THEN G.Field[CX+x, CY+y]:=col END
END
END RegisterFig;
(* Test, if Figure fits to given Position *)
PROCEDURE TestFig(G: Game; x, y, fi, pos: INTEGER): BOOLEAN;
VAR CountX, CountY, col: INTEGER;
BEGIN
FOR CountX:= 0 TO 3 DO
FOR CountY:= 0 TO 3 DO
col:=Fig[fi, pos,CountX,CountY];
IF (col#0) & (G.Field[CountX+x, CountY+y]#0) THEN RETURN FALSE END
END
END;
RETURN TRUE;
END TestFig;
(* Calc Size of one Kasten, depending on Size of Frame *)
PROCEDURE CalcKasten(f: Frame; x, y, w, h: INTEGER);
VAR XKasten, YKasten: INTEGER;
BEGIN
f.Aktiv:=TRUE;
YKasten:=(h-ObenOffset-UntenOffset) DIV YAnzahl;
IF f.G.ShowNext THEN
XKasten:=(w-2*SeitenOffset) DIV (XAnzahl-NextXPos)
ELSE
XKasten:=(w-2*SeitenOffset) DIV XAnzahl;
END;
IF (XKasten<MinKasten) OR (YKasten<MinKasten) THEN
f.Aktiv:=FALSE;
RETURN;
END;
IF XKasten<YKasten THEN
f.Kasten:=XKasten
ELSE
f.Kasten:=YKasten;
END;
IF f.G.ShowNext THEN
f.XOffset:=x+(w-f.Kasten*(XAnzahl+NextXPos)) DIV 2
ELSE
f.XOffset:=x+(w-f.Kasten*XAnzahl) DIV 2;
END;
f.YOffset:=y+(h-f.Kasten*YAnzahl) DIV 2;
END CalcKasten;
(* Redraw Field *)
PROCEDURE RedrawField(f: Frame);
VAR XD, YD: INTEGER;
BEGIN
FOR YD:=1 TO YAnzahl DO
FOR XD:=1 TO XAnzahl DO
IF f.G.Field[XD, YD]=0 THEN
ClearKasten(f, XD, YD)
ELSE
DrawKasten(f, XD, YD, f.G.Field[XD, YD])
END
END
END RedrawField;
(* Search and Delete full Lines *)
PROCEDURE KillLines(f: Frame);
VAR CountX, CountY, Killed: INTEGER;
PROCEDURE KillLine(VAR G: Game; l: INTEGER);
VAR CountX, CountY: INTEGER;
BEGIN
FOR CountY:=l+1 TO YAnzahl DO
FOR CountX:=1 TO XAnzahl DO
G.Field[CountX, CountY-1]:=G.Field[CountX, CountY]
END
END;
FOR CountX:=1 TO XAnzahl DO
G.Field[CountX, YAnzahl]:=0
END
END KillLine;
BEGIN
Killed:=0;
FOR CountY:=YAnzahl-1 TO 1 BY -1 DO
CountX:=1;
LOOP
IF f.G.Field[CountX, CountY]=0 THEN EXIT; END;
IF CountX=XAnzahl THEN
INC(Killed);
KillLine(f.G, CountY);
EXIT;
END;
INC(CountX)
END
END;
IF Killed#0 THEN
RedrawField(f);
f.G.Lines:=f.G.Lines+Killed;
f.G.Score:=Killed*2-1+f.G.Score
END;
IF (f.G.Lines DIV LinesProLevel)>f.G.Level THEN
INC(f.G.Level); INC(f.G.Score, LinesProLevel DIV 2);
f.G.Delay:=(f.G.Delay * (100-SpeedUpProLevel)) DIV 100
END KillLines;
(* Clear Field *)
PROCEDURE ClearField(G: Game);
VAR XDum, YDum: INTEGER;
BEGIN
FOR XDum:= 1 TO XAnzahl DO
FOR YDum:=1 TO YAnzahl DO
G.Field[XDum, YDum]:=0
END
END;
FOR YDum:=0 TO YAnzahl DO
G.Field[0, YDum]:=1;
G.Field[XAnzahl+1, YDum]:=1;
END;
FOR XDum:=0 TO XAnzahl+1 DO
G.Field[XDum, 0]:=1;
G.Field[XDum, YAnzahl+1]:=1
END ClearField;
(* Clear Frame and Draw everything necessary *)
PROCEDURE ClearFrame(f: Frame; x, y, w, h: INTEGER);
VAR XDum, YDum: INTEGER;
BEGIN
Oberon.RemoveMarks(x, y, w, h);
Display.ReplConst(Display.black, x, y, w, h, Display.paint);
IF f.Aktiv THEN
XDum:=f.Kasten*XAnzahl+1;
YDum:=f.Kasten*YAnzahl;
Display.ReplConst(Display.white, f.XOffset-3, f.YOffset-3, XDum+4, YDum+3, Display.paint);
Display.ReplConst(Display.black, f.XOffset-1, f.YOffset-1, XDum, YDum+1, Display.paint);
IF f.G.ShowNext THEN
XDum:=f.XOffset+f.Kasten*NextXPos-3;
YDum:=f.YOffset+f.Kasten*NextYPos-3;
Display.ReplConst(Display.white, XDum, YDum, 4*f.Kasten+5, 2*f.Kasten+5, Display.paint);
Display.ReplConst(Display.black, XDum+2, YDum+2, 4*f.Kasten+1, 2*f.Kasten+1, Display.paint);
END;
RedrawField(f);
IF f.G.Runs THEN
DrawFig(f, f.G.x, f.G.y, f.G.fig, f.G.p);
IF f.G.ShowNext THEN DrawFig(f, NextXPos+1, NextYPos+1, f.G.next, 0) END
END
END ClearFrame;
(* copy frame with same data *)
PROCEDURE CopyMe(f: Frame): Frame;
VAR nf: Frame;
BEGIN
NEW(nf);IF nf=NIL THEN RETURN NIL;END;
nf.handle:=f.handle;
nf.G:=f.G;
RETURN nf;
END CopyMe;
(* Open MenuFrame with ObTris.Menu.Text *)
PROCEDURE MenuFrame(): TextFrames.Frame;
mf: TextFrames.Frame;
buf: Texts.Buffer;
t: Texts.Text;
r: Texts.Reader;
end: LONGINT;
ch: CHAR;
BEGIN
IF Files.Old("ObTris.Menu.Text")=NIL THEN
mf:=TextFrames.NewMenu("ObTris", Menu)
ELSE
mf:=TextFrames.NewMenu("ObTris", "");
NEW(t);Texts.Open(t, "ObTris.Menu.Text");
Texts.OpenReader(r, t, 0);
REPEAT
Texts.Read(r, ch)
UNTIL r.eot OR (ch=0DX);
IF r.eot THEN
end:=t.len
ELSE
end:=Texts.Pos(r)-1;
END;
NEW(buf); Texts.OpenBuf(buf);
Texts.Save(t, 0, end, buf);Texts.Append(mf.text, buf)
END;
RETURN mf;
END MenuFrame;
(* Open new Text-Frame *)
PROCEDURE OpenViewer(text: Texts.Text);
VAR x, y: INTEGER; v: Viewers.Viewer; cf: TextFrames.Frame;
BEGIN
Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, x, y);
cf := TextFrames.NewText(text, 0);
v := MenuViewers.New(TextFrames.NewMenu("ObTris Hall of Fame", "System.Close System.Copy System.Grow"),
cf, TextFrames.menuH, x, y)
END OpenViewer;
(* Handler of an ObTris Frame *)
PROCEDURE Handler(f: Display.Frame; VAR m: Display.FrameMsg);
VAR self: Frame;
BEGIN
self:=f(Frame);
WITH m: Oberon.InputMsg DO
IF m.id=Oberon.track THEN Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, m.X, m.Y) END
| m: Oberon.CopyMsg DO
m.F:=CopyMe(self)
| m: MenuViewers.ModifyMsg DO
WITH m: MenuViewers.ModifyMsg DO
IF m.H#0 THEN
CalcKasten(self, f.X, m.Y, f.W, m.H);
ClearFrame(self, f.X, m.Y, f.W, m.H)
END
END
| m: ObTrisMsg DO
WITH m: DrawMsg DO
IF m.G=self.G THEN
CalcKasten(self, f.X, f.Y, f.W, f.H);
ClearFrame(self, f.X, f.Y, f.W, f.H)
END
ELSE
END
ELSE
END Handler;
(* get current/marked Frame *)
PROCEDURE GetFrame(VAR f: Display.Frame): BOOLEAN;
VAR v: Viewers.Viewer;
BEGIN
IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN
IF (Oberon.Par.frame # NIL) THEN
f:=Oberon.Par.frame.next;
RETURN TRUE
END
ELSE
v:=Oberon.MarkedViewer();
IF (v.dsc # NIL) & (v.dsc.next # NIL) THEN
f:=v.dsc.next;
RETURN TRUE
END
END;
RETURN FALSE;
END GetFrame;
(* Calc System Speed *)
PROCEDURE CalcSysSpeed(): LONGINT;
EndTime, Time, StartTime, q, Anz: LONGINT;
c: CHAR;
f: Frame;
x, y, fig, p, d: INTEGER;
BEGIN
NEW(f);x:=0; y:=0; fig:=0; p:=0; Anz:=0;
StartTime:=Input.Time(); ch[6]:=CHR(0);
EndTime:=StartTime+Input.TimeUnit; (* replace Input.TimeUnit by 300 at MacOberon and Ceres *)
REPEAT
FOR q:=0 TO 31 DO
IF Input.Available()>0 THEN
Input.Read(c);
IF (c=ch[6]) OR (CAP(c)="P") THEN
ELSIF c=ch[6] THEN
IF TestFig(f.G, x-1, y, fig, p) THEN
ClearFig(f, x, y, fig, p);
DEC(x);
DrawFig(f, x, y, fig, p)
END
ELSIF c=ch[6] THEN
IF TestFig(f.G, x+1, y, fig, p) THEN
ClearFig(f, x, y, fig, p);
INC(x);
DrawFig(f, x, y, fig, p)
END
ELSIF c=ch[6] THEN
d:=p+1; IF d=4 THEN d:=0; END;
IF TestFig(f.G, x, y, fig, d) THEN
ClearFig(f, x, y, fig, p);
DrawFig(f, x, y, fig, d);
p:=d
END
ELSIF c=ch[6] THEN
d:=p-1; IF d=-1 THEN d:=3; END;
IF TestFig(f.G, x, y, fig, d) THEN
ClearFig(f, x, y, fig, p);
DrawFig(f, x, y, fig, d);
p:=d
END
ELSIF c=ch[6] THEN
d:=y;
WHILE TestFig(f.G, x, y-1, fig, p) DO DEC(y); END;
ClearFig(f, x, d, fig, p);
DrawFig(f, x, y, fig, p)
END
END
END;
INC(Anz, 31);
Time:=Input.Time()
UNTIL Time>=EndTime;
RETURN (Anz*(EndTime-StartTime)) DIV Input.TimeUnit; (* replace Input.TimeUnit by 300 at MacOberon and Ceres *)
END CalcSysSpeed;
(* Main-Loop of the Game *)
PROCEDURE GameLoop(f: Frame);
c: CHAR;
DelCount: LONGINT;
x, y, p, fig, next, d: INTEGER;
msg: DrawMsg;
BEGIN
x:=f.G.x; y:=f.G.y; p:=f.G.p; fig:=f.G.fig; next:=f.G.next;
f.G.Runs:=TRUE;
Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
IF f.G.ShowNext THEN DrawFig(f, NextXPos+1, NextYPos+1, next, 0); END;
LOOP
IF TestFig(f.G, x, y-1, fig, p) THEN
ClearFig(f, x, y, fig, p);
DEC(y);
DrawFig(f, x, y, fig, p)
ELSE
RegisterFig(f.G, x, y, fig, p);
KillLines(f);
y:=YAnzahl-2; p:=0; fig:=next; next:=Random(7); x:=((XAnzahl-FigSize[fig]) DIV 2)+1;
IF fig=1 THEN DEC(y); p:=2; END;
IF ~TestFig(f.G, x, y, fig, p) THEN f.G.Runs:=FALSE; EXIT END;
IF f.G.ShowNext THEN
ClearFig(f, NextXPos+1, NextYPos+1, fig, 0);
DrawFig(f, NextXPos+1, NextYPos+1, next, 0);
END;
DrawFig(f, x, y, fig, p);
END;
FOR DelCount:=0 TO f.G.Delay DO
IF Input.Available()>0 THEN
Input.Read(c);
IF (c=ch[5]) OR (CAP(c)="P") THEN EXIT
ELSIF c=ch[0] THEN
IF TestFig(f.G, x-1, y, fig, p) THEN
ClearFig(f, x, y, fig, p);
DEC(x);
DrawFig(f, x, y, fig, p)
END
ELSIF c=ch[1] THEN
IF TestFig(f.G, x+1, y, fig, p) THEN
ClearFig(f, x, y, fig, p);
INC(x);
DrawFig(f, x, y, fig, p)
END
ELSIF (c=ch[2]) & (x#-1) THEN
d:=p+1; IF d=4 THEN d:=0; END;
IF TestFig(f.G, x, y, fig, d) THEN
ClearFig(f, x, y, fig, p);
DrawFig(f, x, y, fig, d);
p:=d
END
ELSIF (c=ch[3]) & (x#-1) THEN
d:=p-1; IF d=-1 THEN d:=3; END;
IF TestFig(f.G, x, y, fig, d) THEN
ClearFig(f, x, y, fig, p);
DrawFig(f, x, y, fig, d);
p:=d
END
ELSIF c=ch[4] THEN
d:=y;
WHILE TestFig(f.G, x, y-1, fig, p) DO DEC(y); END;
ClearFig(f, x, d, fig, p);
DrawFig(f, x, y, fig, p)
END
END
END
END;
IF f.G.Runs THEN
f.G.x:=x; f.G.y:=y; f.G.p:=p; f.G.fig:=fig; f.G.next:=next;
Texts.WriteString(W, "Current ObTris Status -")
ELSE
Texts.WriteString(W, "--- GAME OVER --- ");
RegisterScore(f.G.Score, f.G.Level, f.G.Lines);
END;
Texts.WriteString(W, " Score: ");
Texts.WriteInt(W, f.G.Score*ScoreFakt, 1);
Texts.WriteString(W, " Lines: ");
Texts.WriteInt(W, f.G.Lines, 1);
Texts.WriteString(W, " Level: ");
Texts.WriteInt(W, f.G.Level, 1);
Texts.WriteLn(W);
Texts.Append(Oberon.Log, W.buf);
msg.G:=f.G; Viewers.Broadcast(msg);
END GameLoop;
(* Start New Game *)
PROCEDURE StartNewGame(g: Frame);
VAR msg: DrawMsg;
BEGIN
IF g.Aktiv THEN
g.G.Delay:=Delay;
ClearField(g.G);
g.G.y:=YAnzahl-2; g.G.p:=0; g.G.fig:=Random(7); g.G.next:=Random(7);
g.G.Lines:=0; g.G.Score:=0; g.G.Level:=0; g.G.x:=((XAnzahl-FigSize[g.G.fig]) DIV 2)+1;
IF g.G.fig=1 THEN DEC(g.G.y); g.G.p:=2; END;
msg.G:=g.G; Viewers.Broadcast(msg);
GameLoop(g)
END StartNewGame;
(* Open new ObTris Frame *)
PROCEDURE Open*();
f: Frame;
v: MenuViewers.Viewer;
x, y: INTEGER;
BEGIN
NEW(f); NEW(f.G); f.G.ShowNext:=TRUE; f.Aktiv:=FALSE;
f.handle:=Handler;
Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
v:=MenuViewers.New(MenuFrame(), f, TextFrames.menuH, x, y);
ClearField(f.G);
END Open;
(* Start New Game Command *)
PROCEDURE StartNew*();
VAR f, g: Display.Frame;
BEGIN
IF GetFrame(f) THEN
g:=f;
WITH g: Frame DO
StartNewGame(g)
ELSE
END
END StartNew;
(* Restart Game or Start New *)
PROCEDURE Start*();
VAR f, g: Display.Frame;
BEGIN
IF GetFrame(f) THEN
g:=f;
WITH g: Frame DO
IF g.Aktiv THEN
IF g.G.Runs THEN
GameLoop(g)
ELSE
StartNewGame(g)
END
END
ELSE
END
END Start;
(* Restart Game or Start New *)
PROCEDURE ShowNext*();
f, g: Display.Frame;
msg: DrawMsg;
BEGIN
IF GetFrame(f) THEN
g:=f;
WITH g: Frame DO
g.G.ShowNext:=~g.G.ShowNext;
msg.G:=g.G; Viewers.Broadcast(msg)
ELSE
END
END ShowNext;
(* set new username *)
PROCEDURE SetUser*;
S: Texts.Scanner;
text: Texts.Text;
beg, end, time: LONGINT;
BEGIN
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
Texts.Scan(S);
IF S.class=Texts.Char THEN
IF S.c="^" THEN
Oberon.GetSelection(text, beg, end, time);
IF time=-1 THEN RETURN; END;
Texts.OpenScanner(S, text, beg);
Texts.Scan(S)
ELSE
RETURN
END
END;
IF S.class=Texts.Name THEN
COPY(S.s, Name);
END;
Texts.WriteString(W, "Current Username : ");
Texts.WriteString(W, Name);
Texts.WriteLn(W);
Texts.Append(Oberon.Log, W.buf);
END SetUser;
(* show Hi-Score *)
PROCEDURE Score*;
i: INTEGER;
te: Texts.Text;
BEGIN
NEW(te); te:=TextFrames.Text("");
IF Files.Old("ObTris.Score.Text")=NIL THEN
NEW(te); te:=TextFrames.Text("");
Texts.WriteString(W, " Oberon-Tetris Hall Of Fame ! ");Texts.WriteLn(W);
Texts.WriteString(W, "______________________________________________________");Texts.WriteLn(W)
ELSE
Texts.Open(te, "ObTris.Score.Text");
END;
FOR i:=0 TO 9 DO
Texts.WriteInt(W, i+1, 1); Texts.Write(W, CHR(9));
Texts.WriteString(W, HiName[i]); Texts.Write(W, CHR(9));
Texts.WriteInt(W, HiScore[i]*ScoreFakt, 1); Texts.Write(W, CHR(9));
Texts.WriteInt(W, HiLevel[i], 1); Texts.Write(W, CHR(9));
Texts.WriteInt(W, HiLines[i], 1);
Texts.WriteLn(W);
END;
Texts.WriteLn(W);
Texts.WriteString(W, "Current Username : ");
Texts.WriteString(W, Name);
Texts.WriteLn(W); Texts.WriteLn(W);
PrintKeys();
Texts.Append(te, W.buf);
OpenViewer(te);
END Score;
(* set keys *)
PROCEDURE SetKeys*;
S: Texts.Scanner;
text: Texts.Text;
d, beg, end, time: LONGINT;
c: ARRAY 6 OF CHAR;
BEGIN
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
Texts.Scan(S);
IF (S.class=Texts.Char) & (S.c="^") THEN
Oberon.GetSelection(text, beg, end, time);
IF time=-1 THEN RETURN; END;
Texts.OpenScanner(S, text, beg);
Texts.Scan(S)
END;
FOR d:=0 TO 5 DO
IF (S.class=Texts.Char) & (S.c#CHR(0)) THEN
c[d]:=S.c
ELSIF (S.class=Texts.Int) & (S.i>=0) & (S.i<=9) THEN
c[d]:=CHR(48+S.i)
ELSIF S.class=Texts.Name THEN
IF S.s="UP" THEN c[d]:=CHR(193)
ELSIF S.s="DOWN" THEN c[d]:=CHR(194)
ELSIF S.s="LEFT" THEN c[d]:=CHR(196)
ELSIF S.s="RIGHT" THEN c[d]:=CHR(195)
ELSIF S.s="RETURN" THEN c[d]:=CHR(13)
ELSIF S.s="TAB" THEN c[d]:=CHR(9)
ELSIF S.s="SPACE" THEN c[d]:=" "
ELSIF S.s="ESC" THEN c[d]:=CHR(27)
ELSE c[d]:=S.s[0]
END
ELSE
Texts.WriteString(W, "Wrong Key Or Not Enough Keys!");
Texts.Append(Oberon.Log, W.buf); RETURN
END;
Texts.Scan(S)
END;
FOR d:=0 TO 5 DO ch[d]:=c[d] END;
PrintKeys(); Texts.Append(Oberon.Log, W.buf);
SaveHi(FALSE);
END SetKeys;
(* Create all Figures in Fig *)
PROCEDURE CreateFigures();
VAR a, p, x, y, s, d: INTEGER;
PROCEDURE ClearFig(fi, neu: INTEGER);
BEGIN
FOR x:=0 TO 3 DO
FOR y:=0 TO 3 DO
Fig[fi, neu,x, y]:=0
END
END
END ClearFig;
BEGIN
(* clear all Figures at Pos 0*)
FOR a:=0 TO 6 DO ClearFig(a, 0) END;
(* set Figures at Pos 1*)
FigSize[0]:=2; Fig[0,0,0,0]:=blue; Fig[0,0,1,0]:=blue; Fig[0,0,0,1]:=blue; Fig[0,0,1,1]:=blue;
FigSize[1]:=4; Fig[1,0,0,1]:=red; Fig[1,0,1,1]:=red; Fig[1,0,2,1]:=red; Fig[1,0,3,1]:=red;
FigSize[2]:=3; Fig[2,0,1,1]:=green; Fig[2,0,0,0]:=green; Fig[2,0,1,0]:=green; Fig[2,0,2,1]:=green;
FigSize[3]:=3; Fig[3,0,1,1]:=col1; Fig[3,0,0,1]:=col1; Fig[3,0,1,0]:=col1; Fig[3,0,2,0]:=col1;
FigSize[4]:=3; Fig[4,0,1,1]:=yellow; Fig[4,0,0,0]:=yellow; Fig[4,0,0,1]:=yellow; Fig[4,0,2,1]:=yellow;
FigSize[5]:=3; Fig[5,0,1,1]:=col2; Fig[5,0,2,0]:=col2; Fig[5,0,0,1]:=col2; Fig[5,0,2,1]:=col2;
FigSize[6]:=3; Fig[6,0,1,1]:=col3; Fig[6,0,1,0]:=col3; Fig[6,0,0,1]:=col3; Fig[6,0,2,1]:=col3;
(* generate rotated Figures *)
FOR a:=0 TO 6 DO
FOR p:=1 TO 3 DO
s:=FigSize[a]-1;
IF (s=1) OR (s=2) THEN ClearFig(a, p); END;
FOR x:=0 TO s DO
FOR y:=0 TO s DO
d:=Fig[a, p-1, x, y];
Fig[a, p, s-y, x]:=d
END
END
END
END CreateFigures;
BEGIN
Texts.OpenWriter(W);
Texts.WriteString(W, "ObTris (Oberon-Tetris) V1.0");
Texts.WriteLn(W);
Texts.WriteString(W, "(C) 1 Nov 1995 by Ralf Degner");
Texts.WriteLn(W);
Texts.Append(Oberon.Log, W.buf);
IF Oberon.User="" THEN
Name:="AMIGA"
ELSE
COPY(Oberon.User, Name);
END;
Delay:=CalcSysSpeed();
CreateFigures();
LoadHi();
Seed:=Input.Time();
END ObTris.Open
System.Free ObTris ~